<?php
class MagicSignature {
	
	private $publicKey;
	private $magicPublicKey;
	
	private $modulus;
	private $exponent;
	
	public function __construct($magicPublicKey) {
		$this->setMagicPublicKey($magicPublicKey);
	}
	
	private function setMagicPublicKey($magicPublicKey) {
		
		if(empty($magicPublicKey)) {
			Throw new Exception("MagicPublicKey cannot be empty.");
		}
		
		$this->magicPublicKey = $magicPublicKey;
	}
	
	private function setModulus($modulus) {
		$this->modulus = $modulus;
	}
	
	public function getModulus() {
		return $this->modulus;
	}
	
	
	private function setExponent($exponent) {
		$this->exponent = $exponent;
	}
	
	private function getExponent() {
		return $this->exponent;
	}
	
	private function parseModulusExponentFromMagicPublicKey() {
        
        // remove whitespace
        $text = preg_replace('/\s+/', '', $this->magicPublicKey);

        // parse components
        if (!preg_match('/RSA\.([^\.]+)\.([^\.]+)(.([^\.]+))?/', $text, $matches)) {
            return false;
        }
        
        $this->setModulus($this->base64_url_decode($matches[1]));
        $this->setExponent($this->base64_url_decode($matches[2]));
        
    }
	
    // Remove everything below here to own class.
	private function calculatePublicKey() {
		
        $rsa = new Crypt_RSA();
        $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1;
        $rsa->setHash('sha256');
        $rsa->modulus = new Math_BigInteger($this->modulus, 256);
        $rsa->k = strlen($rsa->modulus->toBytes());
        $rsa->exponent = new Math_BigInteger($this->exponent, 256);
		
        $this->publicKey = $rsa;
    }
    
	public function dataHasValidSignature($signedData, $signature) {
        if(empty($this->publicKey)) {
        	$this->parseModulusExponentFromMagicPublicKey();
        	$this->calculatePublicKey();
        }
        return $this->publicKey->verify($signedData, $signature);
    }
    
    public function magicEnvelopeHasValidSignature(MagicEnvelope $magicEnvelope) {
		$signature = self::base64_url_decode($magicEnvelope->getSignature());
        return $this->dataHasValidSignature($magicEnvelope->getEncodedData(), $signature);
    }
	
    private static function base64_url_decode($input)
    {
        return base64_decode(strtr($input, '-_', '+/'));
    }
}